package com.xyt.imei.core.auth;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;

import com.google.gson.Gson;
import com.luminary.common.framework.core.auth.RoleProvider;
import com.luminary.common.framework.core.auth.TokenValidator;
import com.luminary.common.framework.core.model.SimpleResponse;
import com.luminary.component.util.common.GsonUtil;
import com.xyt.imei.core.meta.CacheKey;
import com.xyt.imei.core.meta.DefaultPage;
import com.xyt.imei.core.meta.ServerInfo;

public class HttpHeaderTokenValidator implements TokenValidator {

	private static final Logger logger = LoggerFactory.getLogger(HttpHeaderTokenValidator.class);
	
	private RedisTemplate<String, String> redisTemplate;
	
	private String rootUrl;
	
	private String tokenHttpHeaderKey;
	
	private RoleProvider<Integer> roleProvider;
	
	public HttpHeaderTokenValidator(RedisTemplate<String, String> redisTemplate, String rootUrl, String tokenHttpHeaderKey, RoleProvider<Integer> roleProvider) {
		this.redisTemplate = redisTemplate;
		this.rootUrl = rootUrl;
		this.tokenHttpHeaderKey = tokenHttpHeaderKey;
		this.roleProvider = roleProvider;
	}
	
	@Override
	public boolean validate(HttpServletRequest request, HttpServletResponse response, Object handler) {
		
		String tokenFromClient = request.getHeader(tokenHttpHeaderKey);
		
		if(redisTemplate.opsForValue().get(ServerInfo.SECURE_KEY) == null)
			return false;
			
		logger.info("-----------------验证token-----------------");
		return Optional.ofNullable(tokenFromClient)
				     .map(token->{
				       // 获取服务器上保存的token
				       String tokenJson =  redisTemplate.opsForValue().get(ServerInfo.CACHE_PREFIX + "_" + CacheKey.TOKEN + "_" + token);
				       logger.info("-----------------token:serverToken="+tokenJson+",clientToken="+token+"-----------------");
				       // 存在token返回true，否则返回false
				       return Optional.ofNullable(tokenJson)
					       			 .map(json->{
					       				 logger.info("-----------------token验证成功-----------------");
					       				 return true;
					       			 })
					       			.orElseGet(()->{
					       			    logger.info("-----------------token验证失败-----------------");
					       			    return false;
					       			});
				    })
				    .orElseGet(()->{
				    	logger.info("-----------------token验证失败,没有token信息!-----------------");
				    	response(response, HttpStatus.UNAUTHORIZED.value(), "用户信息失效，请重新访问！");
				    	response.setStatus(HttpStatus.UNAUTHORIZED.value());
				    	response.addHeader("imei_token", "invalid");
				    	response.addHeader("error_location", rootUrl+DefaultPage.ERROR.getName()+".html?message=用户信息失效，请重新登录或访问公众号");
				    	return false;
				    });

	}
	
	private void response(HttpServletResponse response,int code, String failureMessage){

		SimpleResponse simpleResponse=new SimpleResponse(code + "," +failureMessage);
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json");
		
		Gson gson = GsonUtil.createGson();
		
		String json=gson.toJson(simpleResponse);
		
		try {
			response.getWriter().write(json);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@SuppressWarnings({ "hiding", "unchecked" })
	@Override
	public boolean validateRole(HttpServletRequest request, HttpServletResponse response, Object handler, List<String> role) {
		
		String tokenFromClient = request.getHeader(tokenHttpHeaderKey);
		List<Integer> userRoleList = (List<Integer>) roleProvider.getRoleDetails(tokenFromClient);
		for(String r : role) {
			Integer apiRole = Integer.valueOf(r);
			for(Integer userRole : userRoleList) {
				if(userRole.equals(apiRole))
					return true;
			}
		}
		
		return false;
	}

	@Override
	public boolean validateRoleByName(HttpServletRequest request, HttpServletResponse response, Object handler, String name) {
		return true;
	}
	
}
